#include <stdio.h>
#include <stdlib.h>
#include "dominion.h"
#include "rngs.h"
#include "math.h"
#include <assert.h>
#include <string.h>

void prepRandom(int strm, int seed){
  SelectStream(strm);
  PutSeed((long)seed);
}

int getRandomNumber(int min, int max){
	int number = floor(Random() * ((max-min)+1));
	number += min;
	if(number > max){
		number = max;
	}
	return number;

}

void randomizeSupply(struct gameState *g){
	int i;
	for(i=0; i < 27; i++){
		g->supplyCount[i] = getRandomNumber(0, 40);
	}
}

void randomizeHands(struct gameState *g){
	int players = g->numPlayers;
	int i, j;
	for(i=0; i < players; i++){
		g->handCount[i] = getRandomNumber(0, MAX_HAND);
		for(j = 0; j < g->handCount[i]; j++){
			g->hand[i][j] = getRandomNumber(0, 27);
			if(g->hand[i][j] == 27) g->hand[i][j] = 26;
		}

	}
}

void randomizeDecks(struct gameState *g){
	int players = g->numPlayers;
	int i, j;
	for(i=0; i < players; i++){
		g->deckCount[i] = getRandomNumber(0, MAX_DECK);
		for(j = 0; j < g->deckCount[i]; j++){
			g->deck[i][j] = getRandomNumber(0, 27);
			if(g->deck[i][j] == 27) g->deck[i][j] = 26;
		}

	}
	
}

void randomizeDiscard(struct gameState *g){
	int players = g->numPlayers;
	int i, j;
	for(i=0; i < players; i++){
		g->discardCount[i] = getRandomNumber(0, MAX_DECK);
		for(j = 0; j < g->discardCount[i]; j++){
			g->discard[i][j] = getRandomNumber(0, 27);
			if(g->discard[i][j] == 27) g->discard[i][j] = 26;
		}

	}
	
}
void randomizeTurn(struct gameState *g){
	g->whoseTurn = getRandomNumber(0, g->numPlayers);
}

//randomizeTurn() should be called before calling this


int makeRandomGameState(struct gameState *g){
//	printf("Randomizing Game\n");
	g->numPlayers = getRandomNumber(2, 5);
	if(g->numPlayers == 5) g->numPlayers = 4;
	randomizeSupply(g);
	randomizeDecks(g);
	randomizeDiscard(g);
	randomizeHands(g);
	randomizeTurn(g);
	g->coins = getRandomNumber(0, 20);
	g->numActions = getRandomNumber(0, 5);
	g->numBuys = getRandomNumber(1, 5);
//	printf("Game Randomized\n");
	return 0;
}

//returns how many coin cards are in the current player's hand
int moneyCards(struct gameState *g){
	int mCards = 0;
	int handCount = g->handCount[g->whoseTurn];
	int i;
	for(i=0; i < handCount; i++){
		if(g->hand[g->whoseTurn][i] > 3 && g->hand[g->whoseTurn][i] < 7){
			mCards ++;
		}
	}
	return mCards;
}

int searchForMoney(struct gameState *g){
	int i;
	for(i=0; i < g->deckCount[g->whoseTurn]; i++){
		if(g->deck[g->whoseTurn][i] > 3 && g->deck[g->whoseTurn][i] < 7){
			printf("Found Money in Deck!\n");
			return 1;  //found money!
		}
	}
	for(i=0; i < g->discardCount[g->whoseTurn]; i++){
		if(g->discard[g->whoseTurn][i] > 3 && g->discard[g->whoseTurn][i] < 7){
			printf("Found Money in Discard!\n");
			return 1;  //found money!
		}
	}
	return 0; //didn't find any
}

int testAdventurer(struct gameState *g){
	//int coins = g->coins;
	int actions = g->numActions;
	int buys = g->numBuys;
	
	//make sure there is at least one card in the hand and card being played is in it.
	int handCount = g->handCount[g->whoseTurn];
	if(handCount <= 0){
		handCount = 1;
		g->handCount[g->whoseTurn] = handCount;
	}
	int handPos = getRandomNumber(0, (handCount - 1));
	g->hand[g->whoseTurn][handPos] = adventurer;
	
	int mCardsBefore = moneyCards(g);

	//randomize choices
	int choice1 = getRandomNumber(0, 5);
	int choice2 = getRandomNumber(0, 5);
	int choice3 = getRandomNumber(0, 5);
	
	struct gameState cpy;
	struct gameState *copy = &cpy;

	memcpy(copy, g, sizeof(struct gameState));

	int b = 0;
	int *bonus = &b;
	int result = cardEffect(adventurer, choice1, choice2, choice3, g, handPos, bonus);
	if(result == -1){
		if(memcmp(copy, g, sizeof(struct gameState)) != 0){
			printf("Gamestate changed on negative result\n");
		}
		return -1;
	}
	if(g->numActions != (actions)){
		printf("number of actions changed incorrectly!\n");
	}
	if(g->numBuys != buys){
		printf("number of buys changed!\n");
	}
	int mCardsAfter = moneyCards(g);
	if(mCardsAfter < (mCardsBefore + 2)){
		if(searchForMoney(g) == 1){
			printf("Coin cards not added correctly\n");
		}
		
	}
	if(mCardsAfter > (mCardsBefore +2)){
		printf("Too many coin cards added!\n");
	}


	return 1;
}

int main(int argc, char** argv){
	int strm = 1, seed = 4, min = 2, max = 50;
	if(argc > 1){
		strm = atoi(argv[1]);
	}
	if(argc > 2){
		seed = atoi(argv[2]);
	}
	if(argc > 3){
		min = atoi(argv[3]);
	}
	if(argc > 4){
		max = atoi(argv[4]);
	}
	prepRandom(strm, seed);
	int i;
	struct gameState *g = newGame();
	printf("Testing Adventurer.  It should add coin cards to the hand\n");
	for(i=0; i < 1000; i++){
	
		makeRandomGameState(g);
		testAdventurer(g);
	}
	printf("Test Complete\n");

	return 0;
}
